Add simple MQTT support to subscribe to, publish messages.

Daniel O'Connor 10 years ago
parent
commit
4c267aba3f
3 changed files with 116 additions and 0 deletions
  1. 2 0
      Gemfile
  2. 2 0
      Gemfile.lock
  3. 112 0
      app/models/agents/mqtt_agent.rb

+ 2 - 0
Gemfile

@@ -74,6 +74,8 @@ gem 'slack-notifier', '~> 0.5.0'
74 74
 
75 75
 gem 'therubyracer', '~> 0.12.1'
76 76
 
77
+gem 'mqtt'
78
+
77 79
 group :development do
78 80
   gem 'binding_of_caller'
79 81
   gem 'better_errors'

+ 2 - 0
Gemfile.lock

@@ -160,6 +160,7 @@ GEM
160 160
     mime-types (1.25.1)
161 161
     mini_portile (0.5.3)
162 162
     minitest (5.3.3)
163
+    mqtt (0.2.0)
163 164
     multi_json (1.9.3)
164 165
     multi_xml (0.5.5)
165 166
     multipart-post (2.0.0)
@@ -341,6 +342,7 @@ DEPENDENCIES
341 342
   kaminari (~> 0.15.1)
342 343
   kramdown (~> 1.3.3)
343 344
   liquid (~> 2.6.1)
345
+  mqtt
344 346
   mysql2 (~> 0.3.15)
345 347
   nokogiri (~> 1.6.1)
346 348
   protected_attributes (~> 1.0.7)

+ 112 - 0
app/models/agents/mqtt_agent.rb

@@ -0,0 +1,112 @@
1
+# encoding: utf-8 
2
+require "mqtt"
3
+
4
+module Agents
5
+  class MqttAgent < Agent
6
+    description <<-MD
7
+    The MQTT agent allows both publication to an MQTT topic and subscription to an MQTT topic.
8
+
9
+    Setup your own broker (http://jpmens.net/2013/09/01/installing-mosquitto-on-a-raspberry-pi/) or connect to a cloud service (www.cloudmqtt.com).
10
+
11
+    MQTT is a generic transport protocol for machine to machine communication.
12
+
13
+    You can do things like:
14
+
15
+     * Publish to [RabbitMQ](http://www.rabbitmq.com/mqtt.html)
16
+     * Run [OwnTracks, a location tracking tool](http://owntracks.org/) for iOS and Android
17
+     * Subscribe to your home automation setup like [Ninjablocks](http://forums.ninjablocks.com/index.php?p=/discussion/661/today-i-learned-about-mqtt/p1) or [TheThingSystem](http://thethingsystem.com/dev/supported-things.html)
18
+
19
+    Simply choose a topic (think email subject line) to publish/listen to, and configure your service.
20
+
21
+    Hints:
22
+    Many services run mqtts (mqtt over SSL) often with a custom certificate.
23
+
24
+    You'll want to download their cert and install it locally, specifying the ```certificate_path``` configuration.
25
+
26
+
27
+    Example configuration:
28
+
29
+    <pre><code>{
30
+      'uri' => 'mqtts://user:pass@locahost:8883'
31
+      'ssl' => :TLSv1,
32
+      'ca_file' => './ca.pem',
33
+      'cert_file' => './client.crt',
34
+      'key_file' => './client.key',
35
+      'topic' => 'huginn'
36
+    }
37
+    </code></pre>
38
+
39
+    Subscribe to CloCkWeRX's TheThingSystem instance (thethingsystem.com), where
40
+    temperature and other events are being published.
41
+
42
+    <pre><code>{
43
+      'uri' => 'mqtt://kcqlmkgx:sVNoccqwvXxE@m10.cloudmqtt.com:13858'
44
+      'topic' => 'the_thing_system/demo'
45
+    }
46
+    </code></pre>
47
+
48
+    Subscribe to all topics
49
+    <pre><code>{
50
+      'uri' => 'mqtt://kcqlmkgx:sVNoccqwvXxE@m10.cloudmqtt.com:13858'
51
+      'topic' => '/#'
52
+    }
53
+    </code></pre>
54
+
55
+    Find out more detail on [subscription wildcards](http://www.eclipse.org/paho/files/mqttdoc/Cclient/wildcard.html)
56
+
57
+    MD
58
+
59
+    def validate_options
60
+      # unless options['uid'].present? &&
61
+      #   options['expected_update_period_in_days'].present?
62
+      #   errors.add(:base, "expected_update_period_in_days and uid are required")
63
+      # end
64
+    end
65
+
66
+    def working?
67
+      !recent_error_logs?
68
+    end
69
+
70
+    def default_options
71
+      {
72
+        'uri' => 'mqtts://user:pass@locahost:8883',
73
+        'ssl' => :TLSv1,
74
+        'ca_file' => './ca.pem',
75
+        'cert_file' => './client.crt',
76
+        'key_file' => './client.key',
77
+        'topic' => 'huginn'
78
+      }
79
+    end
80
+
81
+    def mqtt_client
82
+      client = MQTT::Client.new(options['uri'])
83
+
84
+      if options['ssl']
85
+        client.ssl = options['ssl'].to_sym
86
+        client.ca_file = options['ca_file']
87
+        client.cert_file = options['cert_file']
88
+        client.key_file = options['key_file']
89
+      end
90
+
91
+      client
92
+    end
93
+
94
+    def receive(incoming_events)
95
+      mqtt_client.connect do |c|
96
+        incoming_events.each do |event|
97
+          c.publish(options['topic'], payload)
98
+        end
99
+      end
100
+    end
101
+
102
+
103
+    def check
104
+      mqtt_client.connect do |c|
105
+        c.get(options['topic']) do |topic,message|
106
+          create_event :payload => { 'topic' => topic, 'message' => message, 'time' => Time.now.to_i }
107
+        end
108
+      end
109
+    end
110
+
111
+  end
112
+end